<?php
declare (strict_types=1);

namespace app\common\model\admin;

use app\common\model\Base as BaseModel;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;

/**
 * 后台菜单模型
 * Class Menu
 */
class Menu extends BaseModel
{
    // 定义表名
    protected $name = 'admin_menu';

    // 定义表主键
    protected $pk = 'menu_id';

    public function getCreateTimeAttr($value): string
    {
        return $value?date("Y-m-d H:i:s",$value):'';
    }

    public function getUpdateTimeAttr($value): string
    {
        return $value?date("Y-m-d H:i:s",$value):'';
    }

    /**
     * 关联操作权限
     */
    public function menuApi(): \think\model\relation\HasMany
    {
        return $this->hasMany('app\common\model\admin\MenuApi', 'menu_id');
    }

    /**
     * 获取菜单列表
     * @param array $param
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getList(array $param = []): array
    {
        $list = static::getAll($param);
        return $this->getTreeData($list);
    }

    /**
     * 获取菜单列表
     * @param array $param
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getAllList(array $param = []): array
    {
        $list = static::getAll($param);
        return $this->getTreeData($list,0 ,false);
    }

    /**
     * 获取所有菜单
     * @param array $param
     * @param bool $isWhere
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    protected static function getAll(array $param = [], bool $isWhere = false): array
    {
        $where = [];
        if ($isWhere){
            $where = $param;
        }else{
            // 关键词搜索
            !empty($param['search']) && $where[] = ['name', 'like', "%{$param['search']}%"];
        }

        // 菜单列表
        $model = (new static)->addHidden(['menuApi']);
        $list = (new static)->with(['menuApi'])
            ->where($where)
            ->order(['sort' => 'asc', 'create_time' => 'asc'])
            ->select()->toArray();
      
        // 整理菜单绑定的apiID集
        return $model->getMenuApiIds($list);
    }

    /**
     * 获取树状菜单列表
     * @param array|null $menuList
     * @param int $parentId
     * @param bool $state
     * @return array
     */
    protected function getTreeData(?array $menuList, int $parentId = 0, bool $state = true): array
    {
        $data = [];
        foreach ($menuList as $key => $item) {

            if (($item['type'] != 10) && $state) continue;

            if ($item['pid'] == $parentId) {
                $children = $this->getTreeData($menuList, (int)$item['menu_id'], $state);
                !empty($children) && $item['children'] = $children;

                $activePath = $this->getActivePaths($item, $menuList);
                $item['activePath'] = $activePath;
                $item['id'] = (int)$item['menu_id'];
                $item['title'] = $item['name'];

                // 页面操作项 例如: 新增 编辑 删除
                $item['permission'] = array_filter($menuList, function ($val) use ($item){
                    return ($val['type'] == 20) && ($item['menu_id'] == $val['pid']);
                });

                $data[] = $item;
                unset($children);
                unset($activePath);
            }
        }
        return $data;
    }


    private function getActivePaths($item, $menuList): array
    {
        $data = [];
        foreach ($menuList as $key => $menu) {
            if ($menu['child_menu_id'] == $item['menu_id'] && $menu['hidden']) {
                $data[] = $menu['path'];
            }
        }
        return $data;
    }

    /**
     * 整理菜单的api ID集
     * @param array|null $menuList
     * @return array
     */
    private function getMenuApiIds(?array $menuList): array
    {
        foreach ($menuList as &$item) {
            if (!empty($item['menuApi'])) {
                $item['apiIds'] = getArrayColumn($item['menuApi'], 'api_id');
            }
        }
        return $menuList;
    }

    /**
     * 菜单信息
     * @param array|int $where
     * @return Menu|array|null
     */
    public static function detail(array|int $where): Menu|array|null
    {
        return static::get($where);
    }

    /**
     * 获取菜单url集
     * @param $menuIds
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public static function getMenuUrls($menuIds): array
    {
        $urls = [];
        foreach (static::getAll() as $item) {
            in_array($item['menu_id'], $menuIds) && $urls[] = $item['url'];
        }
        return $urls;
    }

}
